package com.googlecode.maratische.google;

import java.sql.SQLException;
import java.util.List;

import org.apache.log4j.Logger;

import com.googlecode.maratische.google.exceptions.AuthenticationException;
import com.googlecode.maratische.google.model.Command;
import com.googlecode.maratische.google.model.CommandUpdateItemMedia;
import com.googlecode.maratische.google.model.Commands;

/**
 * Singleton Коммандный процессор, обеспечивающий фоновую обработку комманд
 * 
 * @author gizatullinm
 * 
 */
public class CommandProcessor implements Runnable {
	static Logger logger = Logger.getLogger(CommandProcessor.class.getName());
	protected DaoAction daoAction;
	private boolean offlineStatus = false;

	private static CommandProcessor commandProcessor = null;

	public static void createCommandProcessor(DaoAction daoAction) {
		commandProcessor = new CommandProcessor(daoAction);
		Thread thread = new Thread(commandProcessor);
		thread.start();
		thread.setPriority(thread.getPriority() - 5);
	}

	public static CommandProcessor getCommandProcessor() {
		return commandProcessor;
	}

	private CommandProcessor(DaoAction daoAction) {
		this.daoAction = daoAction;
	}

	public void createCommand(Commands commandType) throws SQLException, BaseException {
		this.daoAction.getCommandDao().save(Command.createCommand(commandType));
		this.ping();
	}

	public void createCommand(Command command) throws SQLException, BaseException {
		validateCommand(command);
		this.daoAction.getCommandDao().save(command);
		this.ping();
	}
	
	private void validateCommand(Command command) throws BaseException {
		if (Commands.UN_STARRED_ITEM.equals(command.getType())
				|| Commands.STARRED_ITEM.equals(command.getType())) {
			if (command.getString1() == null || command.getString1().length()==0
					|| command.getString2() == null || command.getString2().length()==0) {
				throw new BaseException(MainController.getMainController().getBundleMessage("command.error.create"));
			}
		}
	}
	
	public void ping() {
		// logger.debug("ping");
		synchronized (this) {
			this.notify();
		}
	}

	public void run() {
		while (true) {
			try {
				if (!isOfflineStatus()) {
					List<Command> commands = daoAction.getCommandDao().listByPriority();
					while (commands != null && commands.size() > 0) {
						MainController.getMainController().spinnerEnable();
						Command command = commands.get(0);
						try {
							command.execute(daoAction);
							daoAction.getCommandDao().remove(command);
						} catch (AuthenticationException e) {
							;// пользователь не авторизован. комманды выполнять нельзя.
							break;
						} catch (Exception e) {
							//ошибка при скачивании медиа контента игнорируем, за остальные цепляемся
							if (command instanceof CommandUpdateItemMedia) {
								logger.error(e.getMessage());
//								MainController.getMainController().showError(e);
								daoAction.getCommandDao().remove(command);
							} else {
								throw e;
							}
						}
						if (isOfflineStatus()) {
							break;
						}
						commands = daoAction.getCommandDao().listByPriority();
					}
				}
			} catch (AuthenticationException e) {
				;// пользователь не авторизован. комманды выполнять нельзя.
			} catch (Exception e) {
				MainController.getMainController().showError(e);
			}
			MainController.getMainController().spinnerDisable();
			try {
				synchronized (this) {
					this.wait();
				}
			} catch (InterruptedException e) {
				logger.debug(e.getMessage());
			}
		}
	}

	public boolean isOfflineStatus() {
		return offlineStatus;
	}

	public void setOfflineStatus(boolean offlineStatus) {
		this.offlineStatus = offlineStatus;
	}

}
